package com.yaolonga.dc.exector.mybatisplus;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.yaolonga.dc.core.ConditionNode;
import com.yaolonga.dc.core.GroupNode;
import com.yaolonga.dc.core.NodeParser;
import com.yaolonga.dc.core.enums.ConditionType;
import com.yaolonga.dc.core.enums.LogicType;
import com.yaolonga.dc.core.util.DcApplicationUtil;
import com.yaolonga.dc.core.util.StringUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * @author yaolong
 * @version V1.0.0
 * @program dynamic-condition
 * @description 默认的节点解析器（解析成mybatisPlus 查詢Wrapper）
 * @create 2024-06-02 21:38
 **/
@Slf4j
public class MybatisPlusNodeParser implements NodeParser<QueryChainWrapper> {
    @Override
    public QueryChainWrapper parse(List<GroupNode> nodes, Class<?> entity) {
        // 根据实体类获取baseMapper
        BaseMapper bean = (BaseMapper)DcApplicationUtil.getBean(StringUtil.toLowerCaseFirstOne(entity.getSimpleName()) + "Mapper");
        QueryChainWrapper<?> wrapper = new QueryChainWrapper<>(bean);
        if (nodes != null) {
            for (GroupNode node : nodes) {
                LogicType logicType = node.getLogicType();
                switch (logicType) {
                    case or:
                        wrapper.or(w2 -> {
                            node.getConditions().forEach(conditionNode -> buildConditionNodeWrapper(w2, conditionNode));
                        });
                        break;
                    case and:
                        wrapper.and(w2 -> {
                            node.getConditions().forEach(conditionNode -> buildConditionNodeWrapper(w2, conditionNode));
                        });
                        break;
                }
            }
        }
        return wrapper;
    }

    private static <T> void buildConditionNodeWrapper(QueryWrapper<T> w2, ConditionNode conditionNode) {
        ConditionType type = conditionNode.getType();
        String field = conditionNode.getField();
        Object value = conditionNode.getValue();
        LogicType logicType = conditionNode.getLogicType();
        if (LogicType.or == logicType){
            w2.or();
        }
        switch (type) {
            case greater_than:
                w2.gt(field, value);
                break;
            case less_than:
                w2.lt(field, value);
                break;
            case eq:
                w2.eq(field, value);
                break;
            case like:
                w2.like(field, value);
                break;
            case in:
                w2.in(field, (List) value);
                break;
            case not_in:
                w2.notIn(field, (List) value);
        }
    }
}
